<?php
/*
 * @Descripttion: 框架 redis 驱动缓存类，redis 中以 hash 类型保存缓存数据，key 为 cache:CLIENTID ,field 为缓存 key 名，缓存的数据(复合类型的数据，如数组、对象、资源等)经过 json 编码之后挂在 field 之下。
 * @version:
 * @Author: ewgof
 * @Date: 2020-09-01 11:30:11
 * @LastEditors: ewgof
 * @LastEditTime: 2020-10-25 17:01:51
 */
namespace cw;

use cw\interfaces\CacheInterface;

class RedisCache extends Base implements CacheInterface
{
    protected $t = 0;
    protected $redis = null;
    protected $cache_prefix = '';  // 缓存键名前缀

    public function __construct()
    {
        global $redis;

        if (!$redis) {
            throw new RuntimeException(lang(16));
        }
        if (!empty(config('cache.prefix'))) {
            $this->cache_prefix = config('cache.prefix');
        } else {
            $this->cache_prefix = 'cw_cache:';
        }

        $this->t = time();
    }


    public function get(String $name)
    {
        if (empty($name)) {
            return false;
        }
        $key = $this->cache_prefix . $name;
        if ($this->redis->exists($key)) {
            $data = \json_decode($this->redis->get($key), true);
            $val = $data[$name];
        } else {
            $val = false;
        }
        return $val;
    }


    public function set(String $name, $val, $expire = null)
    {
        if (empty($name)) {
            return false;
        }
        if ($expire === null) {
            $expire = config('cache.expire');
        }
        $data = [$name => $val];
        $r = $this->redis->setex($this->cache_prefix . $name, $expire, json_encode($data));
        return (boolean)$r;
    }

    /**
     * @name: inc
     * @msg: 缓存值自增
     * @param string $name 缓存键名
     * @param integer $step 自增步长，默认为1
     * @return boolean
     */
    public function inc(String $name, $step = 1)
    {
        if (empty($name)) {
            return false;
        }
        if ($this->redis->exists($this->cache_prefix . $name)) {
            $data = json_decode($this->redis->get($this->cache_prefix . $name), true);
            if (!\is_numeric($data[$name])) {
                return false;
            }
            $data[$name] += $step;
            $r = $this->redis->set($this->cache_prefix . $name, json_encode($data));
            return (boolean)$r;
        } else {
            return false;
        }
    }


    /**
     * @name: dec
     * @msg: 缓存值自减
     * @param string $name 缓存键名
     * @param integer $step 自减步长，默认为1
     * @return boolean
     */
    public function dec(String $name, $step = 1)
    {
        if (empty($name)) {
            return false;
        }
        if ($this->redis->exists($this->cache_prefix . $name)) {
            $data = \json_decode($this->redis->get($this->cache_prefix . $name), true);
            if (!\is_numeric($data[$name])) {
                return false;
            }
            $data[$name] += $step;
            $r = $this->redis->set($this->cache_prefix . $name, json_encode($data));
            return (boolean)$r;
        } else {
            return false;
        }
    }

    /**
     * @name: delete
     * @msg: 删除缓存值
     * @param string $name 缓存键名
     * @return boolean
     */
    public function delete(String $name)
    {
        return (boolean)$this->redis->del($this->cache_prefix . $name);
    }


    /**
     * @name: pull
     * @msg: 获取并删除缓存值
     * @param string $name 缓存键名
     * @return mixed
     */
    public function pull(String $name)
    {
        if (empty($name)) {
            return false;
        }

        if ($this->redis->exists($this->cache_prefix . $name)) {
            $data = json_decode($this->redis->get($this->cache_prefix . $name), true);
            $this->redis->del($this->cache_prefix . $name);
            return $data['value'];
        } else {
            return false;
        }
    }


    /**
     * @name: clean
     * @msg: 清除当前用户的全部缓存值
     * @param void
     * @return boolean
     */
    public function clean()
    {
        $keys = $this->redis->keys($this->cache_prefix . '*');
        return $this->redis->delete($keys);
    }


    /**
     * @name: has
     * @msg: 判断缓存值是否存在
     * @param string $name 缓存键名
     * @return boolean
     */
    public function has(String $name)
    {
        if (empty($name)) {
            return false;
        }
        return $this->redis->exists($this->cache_prefix . $name);
    }
}
